import axios from 'axios';
const md5 = require('@/utils/md5');
import { getUploadOssAuth } from '@/api/user';
import Compressor from 'compressorjs';

const SECRET_LIFE = 30;

const ossAuth = {
  host: '',
  policy: '',
  signature: '',
  accessid: '',
  dir: '',
  creatTime: 0
};

const validators = {
  type: (file, { types = [] }) => {
    let fileType = file.type.split('/')[1].toLowerCase();
    return types.indexOf(fileType) !== -1 ? true : false;
  },
  size: (file, { min = 0, max }) => {
    let size = file.size / 1024 / 1024;
    if (size < min || size === 0) return false;
    let flag = false;
    if (max) {
      flag = size <= max ? true : false;
    }
    return flag;
  }
};

const checkFile = (file, rules = [], putResult) => {
  if (!file) {
    putResult('文件不能为空');
    return false;
  }
  if (!file instanceof Blob) {
    putResult('文件格式错误');
    return false;
  }
  let flag = true;
  rules.forEach((item) => {
    if (item.validator && validators[item.validator]) {
      if (!validators[item.validator](file, item.options || {})) {
        flag = false;
        putResult(item.message);
        return;
      }
    }
  });
  return flag;
};

const checkOssAuth = async () => {
  try {
    if (!ossAuth.creatTime) {
      let res = await getUploadOssAuth();
      if (res && res.data) {
        Object.assign(ossAuth, res.data, { creatTime: new Date().getTime() });
        return true;
      } else {
        return false;
      }
    } else {
      if ((new Date().getTime() - ossAuth.creatTime) / 1000 / 60 > SECRET_LIFE) {
        let res = await getUploadOssAuth();
        if (res && res.data) {
          Object.assign(ossAuth, res.data, { creatTime: new Date().getTime() });
          return true;
        } else {
          return false;
        }
      } else {
        return true;
      }
    }
  } catch (error) {
    console.log('error: ', error);
    return false;
  }
};

const compress = async (file, options) => {
  return new Promise((resolve, reject) => {
    let deafultOptions = { quality: 0.6, checkOrientation: false, strict: false };
    let mergeOption = Object.assign({}, deafultOptions, options);
    new Compressor(file, {
      ...mergeOption,
      success(result) {
        resolve(result);
      },
      error(err) {
        resolve(null);
      }
    });
  });
};

const uploadOSS = async ({ file, rules, compressOptions = null }) => {
  try {
    let message = '';
    const putResult = (value) => {
      message = value;
    };
    if (!checkFile(file, rules, putResult)) return Promise.reject({ code: 602, msg: message });
    if (!(await checkOssAuth())) return Promise.reject({ code: 603, msg: '权限校验失败' });
    if (compressOptions) {
      let compressFile = await compress(file, compressOptions);
      if (compressFile) {
        file = compressFile;
      } else {
        return Promise.reject({ code: 604, msg: '压缩失败' });
      }
    }
    const { host, policy, signature, accessid, dir } = ossAuth;
    let fileType = file.type.split('/')[1].toLowerCase();
    let fileName = `${file.name || ''}${new Date().getTime()}`;
    let key = `${md5.hex_md5(fileName)}.${fileType}`;
    let formData = new FormData();
    formData.append('key', `${dir}${key}`);
    formData.append('OSSAccessKeyId', accessid);
    formData.append('policy', policy);
    formData.append('signature', signature);
    formData.append('success_action_status', 200);
    formData.append('file', file);
    let res = await axios.post(host, formData, {
      headers: {
        'Content-Type': 'multipart/form-data;'
      }
    });
    if (res.status === 200) {
      return Promise.resolve({
        code: 200,
        msg: 'success',
        data: { name: fileName, url: `${host}/${dir}${key}` }
      });
    } else {
      return Promise.reject({ code: 601, msg: '请求失败' });
    }
  } catch (err) {
    console.log('error', err);
    return Promise.reject({ code: 600, msg: '未知错误' });
  }
};

const getOssAuth = () => {
  return { ...ossAuth };
};

export { uploadOSS, getOssAuth };
